import { EventClass } from "@lib/alen-helper/base/baseClass";
import { AppAisle } from "@lib/alen-helper/base/appAisle";
import { libLogger } from "@lib/alen-helper/base/logger";
import { concatMap, map, of, Subscription, delay, first } from "rxjs";
import { Application } from "../application/application";

libLogger.init({
    showType: ['info', 'error', 'warn'],
})

export namespace PreloadSDK {
    export type CmdData = Runtime.Controller.Tray.CmdData & Runtime.Controller.Window.CmdData & Runtime.Controller.ComonnCmdData;
}

export class PreloadSDK extends EventClass<{
    sdkReady: string,
    message: Application.Message,
    appReady: string,
}> {
    public readonly aisle: AppAisle<Runtime.PreloadCmdData>;
    private _connSubs: Subscription;
    constructor(
        private readonly id: string,
        private readonly _drive: AppAisle.Drive,
        options: Partial<AppAisle.Options>,
        BaseOptions?: Partial<EventClass.BaseOptions>
    ) {
        super('PreloadSDK', BaseOptions);
        this.aisle = this._newClass(AppAisle, this._drive, options);
        this.aisle.setHandler(this._ipcHandler);
        this._sub();
        this._connSubs = this.aisle.conn()
            .subscribe(() => {
                //...
            });
    }

    private _ipcHandler: Partial<AppAisle.CmdHandlers<Runtime.PreloadCmdData_Client>> = {
        'win_event_message': (data, aisle) => {
            return this.triggerEventEnd('message', data.data.param, null, 'eventData')
                .pipe(map(e => !e.isError));
        }
    }

    private _isSdkReady() {
        if (!this.appid || !this.id || !this._isActivate) return;
        this._log.log(`sdkReady appid: ${this.appid},id: ${this.id!}`);
        this._sdkReady = true;
        this.triggerEvent('sdkReady', this.appid);
    }

    private _sdkReady = false;
    private _isActivate: boolean = false;
    private _appid: string | null = null;

    get appid() {
        return this._appid;
    }

    private _subs: Subscription | null = null;

    private _unSub() {
        if (this._subs) this._subs.unsubscribe();
        this._subs = null;
    }

    private _sub() {
        this._unSub();
        this._subs = this.aisle.event('activate')
            .pipe(concatMap(() => {
                this._isActivate = true;
                return this.aisle.cmd('win_activate', { id: this.id });
            }))
            .pipe(concatMap(info => {
                this._appid = info.appid;
                return of(null);
            }))
            .subscribe(() => {
                this._isSdkReady();
            });
    }

    message(data: Application.Message['data'], target: Partial<Application.Message['target']> = {}) {
        const newTarget: Application.Message['target'] = Object.assign({ appid: this.appid!, id: this.id }, target);
        //return this.aisle.cmd('win_message', { target: newTarget, data });
        if (newTarget.id === this.id && newTarget.appid === this.appid) {
            return this.triggerEventEnd('message', {
                source: { appid: this.appid!, id: this.id },
                target: newTarget,
                data,
            }, null, 'eventData').pipe(map(e => {
                return !e.isError;
            }));
        } else {
            return this.aisle.cmd('win_message', { target: newTarget, data });
        }
    }


    close() {
        return this.aisle.cmd('win_close', { id: null });
    }

    appReady() {
        return of(this._sdkReady)
            .pipe(concatMap(a => {
                if (a) return of(null);
                return this.event('sdkReady')
            }))
            .pipe(first())
            .pipe(concatMap(() => {
                return this.aisle.cmd('win_ready', null);
            }))
            .pipe(map(data => {
                this.triggerEvent('appReady', this.appid!);
                this._log.log(`appReady appid: ${this.appid!},id: ${this.id!}`);
                return this._appid!;
            }));
    }

}